#※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
# File Name: virtualenv.sh
# Author: GID5564
# Description: pipenv虚拟环境
# Created Time: 16/09/23-08:37:54
#※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
#! /bin/bash

export BIN_BOOT=${BASH_SOURCE[0]:-$0}
function __evn_init__(){
    local script_dir=$(cd "$(dirname "${BIN_BOOT}")" &>/dev/null && pwd -P)
    export XSHELL_PATH="${script_dir%/*}"
    source ${XSHELL_PATH}/xlib/core.sh
    
    __install_package__
    
    #PS
    export _OLD_ENV_PS=${_OLD_PS}
    
    #设置环境变量
    #export VIRTUALENVWRAPPER_PYTHON=$(which python3)
    export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3

    export VIRTUALENVWRAPPER_VIRTUALENV=/usr/local/bin/virtualenv
    export VIRTUALENV_USE_DISTRIBUTE=1
    export WORKON_HOME=${SYS_HOME}/.virtualenvs
    export VIRTUALENVWRAPPER_PROJECT_FILENAME=${SYS_HOME}/".project"
    export PIP_VIRTUALENV_BASE=$WORKON_HOME
    export PIP_RESPECT_VIRTUALENV=true
    export VIRTUALENV_ACTIVATE_FILE=/usr/local/bin/virtualenvwrapper.sh
    [[ ! -d ${WORKON_HOME} ]] && mkdir ${WORKON_HOME}
    [[ -s ${VIRTUALENV_ACTIVATE_FILE} ]] && {
        
        source ${VIRTUALENV_ACTIVATE_FILE}
        [[ $? -eq 0 ]] && {
            
            
            virtualenv_str_to_array
            tip "已完成虚拟环境初始化配置!"
            #__auto__
            __virtualenv__
            [[ $? -eq 0 ]] || {
                warn "未创建任何虚拟环境!"
                return 1
            }
        } || {
            error "虚拟环境初始化失败!"
             return 1
        }
        } || {
            warn "相关软件包(virtualenv，virtualenvwrapper)未安装或激活文件[${VIRTUALENV_ACTIVATE_FILE}]丢失!"
            return 1
        }
}



function __virtualenv__(){
    #检查是否有虚拟环境，有就继续
    [[ ${ENV_SUM} -ne 0 ]] && {
        if [[ $ENV_SUM -eq 1 ]]; then
            # 只有一个
            SELECT_ENV=${ARRAY_ENVS[@]}
        elif [[ $ENV_SUM -gt 1 ]]; then
            # 最少二个，选首个
            SELECT_ENV=${ARRAY_ENVS[0]}
        fi
        workon $SELECT_ENV 2>/dev/null
        [[ $? -eq 0 ]] && {
            CUR_ENV=${SELECT_ENV}
            PS1="(${PURPLE}$CUR_ENV${RESET})${_OLD_ENV_PS}"
            local STR_ENVS=${ARRAY_ENVS[@]}
            success "成功打开虚拟环境[${RED}${STR_ENVS}${RESET}${GREEN}]: ${RESET}${YELLOW}$CUR_ENV${RESET}"
            unset STR_ENVS
        }
        return 0
    } || {
        return 1
    }
}

function __auto__(){
    local num
    #检查是否有虚拟环境，有就列出
    [[ ${ENV_SUM} -ne 0 ]] && {
        Msg "${BLUE}需要进入虚拟环境${RESET}${BLUE}吗？［${RESET}${YELLOW}y${RESET}${BLUE}|${RESET}${YELLOW}n${RESET}${BLUE}］${RESET}" 
        read -n 1 yn
        spec_char '\n'
        if [[ $yn = 'y' || $yn = 'Y' ]];then
            virtualenv_list
            if [[ $ENV_SUM -eq 1 ]]; then
                SELECT_ENV=${ARRAY_ENVS[@]}
            elif [[ $ENV_SUM -gt 1 ]]; then
                Msg "${BLUE}按数字选择一个进入:[${RESET}${RED}1${RESET}${BLUE}-${RESEY}${RED}${ENV_SUM}${RESET}${BLUE}] ${RESET}" 
                read -n 1 num
                spec_char '\n'
                ze=`IsNumber $num`
                if [[ ${ze} -eq 1 ]] && [[ ${num} -le ${ENV_SUM} && ${num} -ge 1 ]];
                then
                    SELECT_ENV=${ARRAY_ENVS[$num]}
                else
                    tip "当前未选择虚拟环境!"
                    SELECT_ENV=""
                    return 0
                fi
            fi
            msg "${BLUE}正在打开${YELLOW}${SELECT_ENV}${RESET}${BLUE},退出请输入命令:${RESET}${YELLOW}qv${RESET}" 
            workon $SELECT_ENV 2>/dev/null
            local ret=$?
            [[ ${ret} -eq 0 ]] && {
                CUR_ENV=${SELECT_ENV}
                PS1="(${PURPLE}$CUR_ENV${RESET})${_OLD_ENV_PS}"
                success "成功打开虚拟环境: $CUR_ENV"

            } || {
                error "出现未知错误,虚拟环境未打开!"
            }
            unset ret
        fi
        unset num
    }
}

function open_env(){
    local senv=$1
    local isHav=0
    for ((i=1;i<=ENV_SUM;i++)) ;   
    do
        if [[ $senv == ${ARRAY_ENVS[$i]} ]]; then
            isHav=1
            break
        fi
    done
    [[ $isHav -eq 1 ]] && {
        workon $senv 2>/dev/null
        local ret=$?
        [[ $ret -eq 0 ]] && {
            CUR_ENV=${senv}
            PS1="(${PURPLE}$CUR_ENV${RESET})${_OLD_ENV_PS}"

            success "成功打开虚拟环境: $senv"
        } || { 
            error "出现未知错误,虚拟环境未打开!"
        }
        unset ret
    } || {
        warn "${senv} 环境名称不存在!"
    }
    unset senv isHav
}

function __install_package__() {
    local installed=$(read_ini "${FILE_CONFIG}" "env-enable" "installed")
    if [[ "${installed}" != "true" ]]; then
        msg "${BLUE}安装相关包及依赖…${RESET}"
        
        install_dpkg_package "licenseutils" || { error "licenseutils 安装失败！"; return 1; }
        install_python_package "virtualenv" || { error "virtualenv 安装失败！"; return 1; }
        install_python_package "virtualenvwrapper" || { error "virtualenvwrapper 安装失败！"; return 1; }
        
        if command -v virtualenv >/dev/null 2>&1 && command -v virtualenvwrapper >/dev/null 2>&1; then
            write_ini "${FILE_CONFIG}" "env-enable" "installed" "true"
            success "安装成功，已更新配置状态。"
        else
            warn "安装后验证失败，请手动检查！"
            return 1
        fi
    fi
    unset installed
}



function remove_virtualenv(){
    #移除虚拟环境
    local ise=$(read_ini "env-enable" "installed")
    if [[ ${ise} = "true" ]];then
        Msg "${WARN}确定要移除整个虚拟环境？${RESET}${BLUE}[${RESET}${YELLOW}y${RESET}${BLUE}|${RESET}${YELLOW}n${RESET}${BLUE}] ${RESET}" 
        read -n 1 yn
        spec_char '\n'   
        case ${yn} in
        y|Y)
            pip uninstall -y "virtualenv"
            pip uninstall -y "virtualenvwrapper"
            write_ini "env-enable" "installed" "false"
            success "已移除虚拟环境!"
            ;;
        *)
            ;;
        esac
    else
        warn "虚拟环境未安装!"
    fi
}

function virtualenv_main(){
    #virtualenv_init
    #virtualenv_str_to_array
    virtualenv_menu
}
function virtualenv_str_to_array(){
    ##字符串格式化，字符串转为数组
    ENVS=(`lsvirtualenv -b |grep "[A-Za-z0-9_]" |awk -v RS='' '{gsub("\n"," "); print}'`)
    #虚拟环境总数
    ENV_SUM=${#ENVS[*]}
    #环境名数组
    ARRAY_ENVS=(${ENVS[*]})
    CUR_ENV=""
}
function virtualenv_list(){
    #virtualenv_str_to_array
    if [[ $ENV_SUM -ne 0 ]];then
        for ((i=0;i<$ENV_SUM;i++))
        do
            msg "${BLUE}[${RESET}${RED}${i}${RESET}${BLUE}]:${RESET} ${YELLOW}${ARRAY_ENVS[$i]}${RESET}" 
        done
    else
        alert "虚拟环境列表为空!"
    fi
}
function open_virtualenv(){
    local SELECT_ENV
    if [[ $ENV_SUM -eq 1 ]]; then
        SELECT_ENV=${ARRAY_ENVS[@]}
        msg "${BLUE}正在打开${YELLOW}${SELECT_ENV}${RESET}${BLUE},退出请输入命令:${RESET}${YELLOW}qv${RESET}"
    elif [[ $ENV_SUM -eq 0 ]]; then
        tip "虚拟环境不存在或未创建!"
        retturn 1
    else
        Msg "${BLUE}按数字选择一个进入:[${RESET}${RED}1${RESET}${BLUE}-${RESEY}${RED}${ENV_SUM}${RESET}${BLUE}] ${RESET}" 
        read -n 1 num
        spec_char '\n'
        while [[ -n $num ]]; 
        do
            ze=`IsNumber $num`
            if [[ ${ze} -eq 1 ]] && [[ "${num}" -le "${ENV_SUM}" ]] && [[ "${num}" -ge 1 ]]; then
                break
            fi
           
            virtualenv_list
                
            Msg "${BLUE}请重新选择一个进入:[${RESET}${RED}1${RESET}${BLUE}-${RESEY}${RED}${ENV_SUM}${RESET}${BLUE}] ${RESET}" 
            read -n 1 num
            spec_char '\n'
        done
        SELECT_ENV=${ARRAY_ENVS[$num]}
        msg "${BLUE}正在打开${YELLOW}${SELECT_ENV}${RESET}${BLUE},退出请输入命令:${RESET}${YELLOW}qv${RESET}" 
    fi
    workon $SELECT_ENV 2>/dev/null
    local ret=$?
    [[ ${ret} -eq 0 ]] && {
        CUR_ENV=${SELECT_ENV}
        PS1="(${PURPLE}$CUR_ENV${RESET})${_OLD_ENV_PS}"
        success "成功打开虚拟环境: $CUR_ENV"
    } || {
        error "出现未知错误,虚拟环境未打开!"
    }
    unset ret
}
function add_virtualenv(){
    local name
    Msg "${BLUE}请为虚拟环境命名: ${RESET}" 
    read name
    [[ -z ${name} ]] && {
        error "名称不能为空!"
        return 1
    }
    #spec_char '\n'
    msg "${BLUE}正在创建虚拟环境${RESET} ${RED}${name}${RESET} ${BLUE}……${RESET}"
    mkvirtualenv -p /usr/bin/python3 $name
    [[ $? -ne 0 ]] && {
        error "出现未知错误，虚拟环境${name}创建失败!"
        return 1
    }
    success "${GREEN}创建成功。${RESET}"
    #刷新数组
    virtualenv_str_to_array
    Msg "${BLUE}需要进入虚拟环境 ${RESET}${RED}${name}${RESET} ${BLUE}吗？［${RESET}${YELLOW}y${RESET}${BLUE}|${RESET}${YELLOW}n${RESET}${BLUE}］${RESET}" 
    read -n 1 yn
    spec_char '\n'
    if [[ $yn = 'y' || $yn = 'Y' ]];then
        workon $name 2>/dev/null
        local ret=$?
        [[ ${ret} -eq 0 ]] && {
            CUR_ENV=${name}
            PS1="(${PURPLE}$CUR_ENV${RESET})${_OLD_ENV_PS}"
            success "成功打开虚拟环境: $CUR_ENV"
        } || {
            error "出现未知错误,虚拟环境未打开!"
        }
        unset ret
    fi
}
function del_virtualenv(){
    local SELECT_ENV
    if [[ $ENV_SUM -eq 1 ]]; then
        SELECT_ENV=${ARRAY_ENVS[@]}
    else
        Msg "${BLUE}请选择删除项:[${RESET}${RED}1${RESET}${BLUE}-${RESET}${RED}${ENV_SUM}${RESET}${BLUE}] ${RESET}" 
        read -n 1 num
        spec_char '\n'
        while [[ -n $num ]]; 
        do
            ze=`IsNumber $num`
            if [[ $ze -eq 1 ]] && [[ $num -le $ENV_SUM ]] && [[ $num -ge 1 ]]; then
                break
            fi
           
            virtualenv_list
                
            Msg "${BLUE}请重新选择删除项:[${RESET}${RED}1${RESET}${BLUE}-${RESET}${RED}${ENV_SUM}${RESET}${BLUE}] ${RESET}" 
            read -n 1 num
            spec_char '\n'
        done
    
        SELECT_ENV=${ARRAY_ENVS[$num]}
    fi
            
    Msg "${WARN}确定要删除虚拟环境: ${RESET}${RED}${SELECT_ENV}${RESET}${RED} ${RESET}${BLUE}？[${RESET}${YELLOW}y${RESET}${BLUE}|${RESET}${YELLOW}n${RESET}${BLUE}] ${RESET}" 
    read -n 1 yn
    spec_char '\n'
    case "$yn" in
    y|Y) 
        rmvirtualenv $SELECT_ENV
        msg "${GREEN}已成功删除虚拟环境: ${RESET}${RED}${SELECT_ENV}${RESET}"
        #刷新数组
        virtualenv_str_to_array
        ;;
    *) ;;
    esac
    
}
function quit_virtualenv(){
    if [[ -z ${CUR_ENV} ]];then
        warn "${YELLOW}当前未处于虚拟环境中!${RESET}"
    else
        deactivate
        msg "${GREEN}已成功退出当前虚拟环境: ${RESET}${RED}${CUR_ENV}${RESET}"
        CUR_ENV=""
        PS1="${_OLD_ENV_PS}"
    fi
}























__evn_init__